"""
Command-line interface for OSS (GPT-OSS via Ollama) client
"""

import argparse
import sys
import json
from pathlib import Path
from typing import Optional, Dict

from .oss_core import OSSClient, OSSConfig
from .utils import setup_logging, load_env_file, validate_api_key
from .history import QAHistoryManager


def create_simple_parser():
    """Create parser for simple interface (like oss-client)."""
    parser = argparse.ArgumentParser(
        description="OSS Client - GPT-OSS via Ollama for text analysis and question answering"
    )

    parser.add_argument("prompt", nargs="?", help="Text prompt to ask OSS model")
    parser.add_argument("--file", "-f", type=str, help="File containing text to use as prompt")

    parser.add_argument("--list", action="store_true", help="List all Q&A history with question IDs")
    parser.add_argument("--show", type=int, metavar="QUESTION_ID", help="Show full Q&A for specific question ID")

    parser.add_argument("--config", type=str, help="Path to config file")
    parser.add_argument("--api-key", type=str, help="OSS API key (if required)")
    parser.add_argument("--base-url", type=str, help="API base URL, defaults to OLLAMA_BASE_URL or http://60.245.128.27:11434")
    parser.add_argument("--model", type=str, help="Model name, defaults to OLLAMA_MODEL_ID or gpt-oss:120b")
    parser.add_argument("--log-level", type=str, default="INFO", choices=["DEBUG", "INFO", "WARNING", "ERROR"], help="Logging level")
    parser.add_argument("--log-file", type=str, help="Log file path")
    parser.add_argument("--env-file", type=str, help="Environment file path")
    parser.add_argument("--system-prompt", type=str, help="System prompt for simple mode")

    return parser


def create_subcommand_parser():
    """Create parser for advanced subcommand interface."""
    parser = argparse.ArgumentParser(
        description="OSS Client - GPT-OSS via Ollama for text analysis and question answering"
    )

    parser.add_argument("--config", type=str, help="Path to config file")
    parser.add_argument("--api-key", type=str, help="OSS API key (if required)")
    parser.add_argument("--base-url", type=str, help="API base URL, defaults to OLLAMA_BASE_URL or http://60.245.128.27:11434")
    parser.add_argument("--model", type=str, help="Model name, defaults to OLLAMA_MODEL_ID or gpt-oss:120b")
    parser.add_argument("--log-level", type=str, default="INFO", choices=["DEBUG", "INFO", "WARNING", "ERROR"], help="Logging level")
    parser.add_argument("--log-file", type=str, help="Log file path")
    parser.add_argument("--env-file", type=str, help="Environment file path")

    subparsers = parser.add_subparsers(dest="command", help="Available commands", required=True)

    ask_parser = subparsers.add_parser("ask", help="Ask OSS model a question")
    ask_parser.add_argument("question", type=str, help="Question to ask")
    ask_parser.add_argument("--system-prompt", type=str, help="System prompt")
    ask_parser.add_argument("--chinese", action="store_true", help="Use Chinese technical response mode")
    ask_parser.add_argument("--domain", type=str, default="技术", help="Technical domain for Chinese mode")
    ask_parser.add_argument("--context-file", type=str, help="JSON file containing context information")
    ask_parser.add_argument("--output", type=str, help="Output file path")

    batch_parser = subparsers.add_parser("batch", help="Ask multiple questions")
    batch_parser.add_argument("questions_file", type=str, help="File containing questions (one per line or JSON)")
    batch_parser.add_argument("--output-dir", type=str, help="Output directory for answers")
    batch_parser.add_argument("--system-prompt", type=str, help="System prompt")
    batch_parser.add_argument("--chinese", action="store_true", help="Use Chinese technical response mode")

    subparsers.add_parser("test", help="Test API connection")

    return parser


def main():
    """Main CLI entry point."""
    known_commands = ["ask", "batch", "test"]
    use_subcommands = len(sys.argv) > 1 and sys.argv[1] in known_commands

    if use_subcommands:
        parser = create_subcommand_parser()
        args = parser.parse_args()
    else:
        parser = create_simple_parser()
        args = parser.parse_args()

    logger = setup_logging(args.log_level, args.log_file)

    if args.env_file:
        load_env_file(args.env_file)
    else:
        load_env_file()

    try:
        config = create_config_from_args(args)
        client = OSSClient(config, logger)

        if hasattr(args, "command") and args.command:
            if args.command == "ask":
                handle_ask_command(client, args, logger)
            elif args.command == "batch":
                handle_batch_command(client, args, logger)
            elif args.command == "test":
                handle_test_command(client, logger)
        elif hasattr(args, "list") and args.list:
            handle_history_list_command(logger)
        elif hasattr(args, "show") and args.show:
            handle_history_show_command(args.show, logger)
        elif hasattr(args, "prompt") and (args.prompt or args.file):
            handle_simple_command(client, args, logger)
        else:
            if len(sys.argv) > 1 and sys.argv[1] in known_commands:
                create_subcommand_parser().print_help()
            else:
                create_simple_parser().print_help()
            sys.exit(1)

    except Exception as e:
        logger.error(f"Error: {e}")
        sys.exit(1)


def create_config_from_args(args) -> OSSConfig:
    """Create OSSConfig from command line arguments."""
    try:
        config = OSSConfig.auto_config()
    except ValueError as e:
        if not (hasattr(args, "api_key") and args.api_key):
            raise ValueError(f"Configuration failed: {e}. Set OSS_BASE_URL/OLLAMA_BASE_URL or use --base-url")
        config = OSSConfig(api_key="", skip_validation=True)

    if hasattr(args, "api_key") and args.api_key:
        config.api_key = args.api_key
        config.skip_validation = False
    if hasattr(args, "base_url") and args.base_url:
        config.base_url = args.base_url
    if hasattr(args, "model") and args.model:
        config.model_name = args.model

    if not config.skip_validation and not validate_api_key(config.api_key):
        raise ValueError("Valid API key required. Set OSS_API_KEY or use --api-key, or set OSS_SKIP_API_VALIDATION=true")

    return config


def _load_context(context_file: Optional[str], logger) -> Dict[str, str]:
    if not context_file:
        return {}

    context_path = Path(context_file)
    if not context_path.exists():
        logger.warning(f"Context file not found: {context_path}")
        return {}

    with open(context_path, "r", encoding="utf-8") as f:
        try:
            context = json.load(f)
            if not isinstance(context, dict):
                raise ValueError("Context JSON must be an object (dictionary).")
            logger.info(f"Loaded context from: {context_path}")
            return context
        except json.JSONDecodeError as exc:
            logger.error(f"Invalid context JSON: {exc}")
            raise


def handle_ask_command(client: OSSClient, args, logger):
    """Handle ask command."""
    context = _load_context(args.context_file, logger)

    if args.chinese:
        response = client.ask_chinese_technical(args.question, context, args.domain)
    elif context:
        response = client.ask_with_context(args.question, context, args.system_prompt)
    else:
        response = client.ask(args.question, args.system_prompt)

    if args.output:
        output_path = Path(args.output)
        with open(output_path, "w", encoding="utf-8") as f:
            f.write(response)
        logger.info(f"Response saved to: {output_path}")
    else:
        print(response)


def handle_batch_command(client: OSSClient, args, logger):
    """Handle batch command."""
    questions_path = Path(args.questions_file)
    if not questions_path.exists():
        raise FileNotFoundError(f"Questions file not found: {questions_path}")

    with open(questions_path, "r", encoding="utf-8") as f:
        content = f.read().strip()

    try:
        data = json.loads(content)
        if isinstance(data, list):
            questions = data
        elif isinstance(data, dict) and "questions" in data:
            questions = data["questions"]
        else:
            raise ValueError("Invalid JSON format")
    except json.JSONDecodeError:
        questions = [line.strip() for line in content.split("\n") if line.strip()]

    logger.info(f"Loaded {len(questions)} questions")
    results = client.batch_ask(questions, args.system_prompt)

    if args.output_dir:
        output_dir = Path(args.output_dir)
        output_dir.mkdir(parents=True, exist_ok=True)

        for idx, (question, answer) in enumerate(results.items(), start=1):
            filename = f"answer_{idx:03d}.md"
            answer_file = output_dir / filename
            with open(answer_file, "w", encoding="utf-8") as f:
                f.write(f"# Question {idx}\n\n")
                f.write(f"**Question**: {question}\n\n")
                f.write(f"**Answer**:\n\n{answer}\n")
            logger.info(f"Answer {idx} saved to: {answer_file}")

        summary_file = output_dir / "summary.json"
        with open(summary_file, "w", encoding="utf-8") as f:
            json.dump(results, f, indent=2, ensure_ascii=False)
        logger.info(f"Summary saved to: {summary_file}")
    else:
        for idx, (question, answer) in enumerate(results.items(), start=1):
            print(f"\n=== QUESTION {idx} ===")
            print(question)
            print(f"\n=== ANSWER {idx} ===")
            print(answer)
            print("\n" + "=" * 50)


def handle_test_command(client: OSSClient, logger):
    """Handle test command."""
    logger.info("Testing connection to OSS (GPT-OSS via Ollama) endpoint...")
    try:
        if client.validate_connection():
            logger.info("✅ Connection test successful")
            print("Connection to OSS endpoint is working correctly")
        else:
            logger.error("❌ Connection test failed")
            print("Failed to connect to OSS endpoint")
            sys.exit(1)
    except Exception as e:
        logger.error(f"❌ Connection test error: {e}")
        print(f"Connection test failed with error: {e}")
        sys.exit(1)


def handle_simple_command(client: OSSClient, args, logger):
    """Handle simple interface commands."""
    prompt = ""
    output_file = None

    if args.file:
        file_path = Path(args.file)
        if not file_path.exists():
            logger.error(f"File not found: {file_path}")
            sys.exit(1)

        with open(file_path, "r", encoding="utf-8") as f:
            prompt = f.read().strip()

        logger.info(f"Loaded prompt from: {file_path}")

        if file_path.suffix.lower() in [".md", ".markdown"]:
            stem = file_path.stem
            output_file = file_path.parent / f"{stem}_answer{file_path.suffix}"

    elif args.prompt:
        prompt = args.prompt
    else:
        logger.error("Either prompt text or --file must be provided")
        sys.exit(1)

    if not prompt:
        logger.error("No prompt text found")
        sys.exit(1)

    logger.info("Sending prompt to OSS model...")
    try:
        response = client.ask(prompt, args.system_prompt)
        if output_file:
            with open(output_file, "w", encoding="utf-8") as f:
                f.write(response)
            logger.info(f"Response saved to: {output_file}")
        else:
            print(response)
    except Exception as e:
        logger.error(f"Error getting response: {e}")
        sys.exit(1)


def handle_history_list_command(logger):
    """Handle --list command to show Q&A history."""
    try:
        history_manager = QAHistoryManager()
        entries = history_manager.get_entries(limit=50)

        if not entries:
            print("No Q&A history found.")
            return

        print(f"Found {len(entries)} Q&A entries:\n")
        print(f"{'ID':<5} {'Model':<10} {'Date':<20} {'Question':<60}")
        print("-" * 95)

        for entry in entries:
            date_str = entry.timestamp.strftime("%Y-%m-%d %H:%M:%S") if entry.timestamp else "Unknown"
            chinese_indicator = " (中文)" if entry.chinese_mode else ""
            domain_info = f" [{entry.domain}]" if entry.domain else ""
            print(f"{entry.id:<5} {entry.model:<10} {date_str:<20} {entry.question_preview:<60}")
            if chinese_indicator or domain_info:
                print(f"{'':26}{chinese_indicator}{domain_info}")

        stats = history_manager.get_statistics()
        print(f"\n📊 Statistics:")
        print(f"   Total entries: {stats['total_entries']}")
        print(f"   Qwen entries: {stats['qwen_entries']}")
        print(f"   DeepSeek entries: {stats['deepseek_entries']}")
        print(f"   OSS entries: {stats['oss_entries']}")
        print(f"   Chinese entries: {stats['chinese_entries']}")
        print(f"   Recent (7 days): {stats['recent_entries']}")
        if stats["avg_response_time"]:
            print(f"   Avg response time: {stats['avg_response_time']:.2f}s")

    except Exception as e:
        logger.error(f"Error listing history: {e}")
        sys.exit(1)


def handle_history_show_command(question_id: int, logger):
    """Handle --show command to display specific Q&A entry."""
    try:
        history_manager = QAHistoryManager()
        entry = history_manager.get_entry(question_id)

        if not entry:
            print(f"No Q&A entry found with ID {question_id}")
            sys.exit(1)

        print(f"ID: {entry.id}")
        print(f"Model: {entry.model}")
        if entry.timestamp:
            print(f"Date: {entry.timestamp.strftime('%Y-%m-%d %H:%M:%S')}")
        if entry.system_prompt:
            print(f"System Prompt: {entry.system_prompt}")
        if entry.chinese_mode:
            print("Chinese Mode: Enabled")
        if entry.domain:
            print(f"Domain: {entry.domain}")
        if entry.response_time is not None:
            print(f"Response Time: {entry.response_time:.2f} seconds")
        if entry.tokens_used is not None:
            print(f"Tokens Used: {entry.tokens_used}")
        if entry.context:
            print("\nContext:")
            for key, value in entry.context.items():
                snippet = value[:200] + ("..." if len(value) > 200 else "")
                print(f"- {key}: {snippet}")

        print("\nQuestion:\n")
        print(entry.question)
        print("\nAnswer:\n")
        print(entry.answer)

    except Exception as e:
        logger.error(f"Error showing history entry: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()
